﻿// // ******************************************************************
// //       /\ /|       @file       AutoTranslationSubBackgroundService.cs
// //       \ V/        @brief      await29
// //       | "")       @author     Await, 285283010@qq.com
// //       /  |
// //      /  \\        @Modified   2025-02-20 21:02
// //    *(__\_\        @Copyright  Copyright (c) , 2025-02-04 14:02 Await
// // ******************************************************************

using AutomaticSubtitles.Service.Application.LanguageConversion.Queries;
using AutomaticSubtitles.Service.Application.Media.Queries;
using AutomaticSubtitles.Service.Application.Translate.Interface.Queries;
using AutomaticSubtitles.Service.Application.Translate.Service.Commands;
using AutomaticSubtitles.Service.Application.Translate.Service.Queries;
using AutomaticSubtitles.Service.Application.TranslationRecord.Queries;
using AutomaticSubtitles.Service.DataAccess.Model;

namespace AutomaticSubtitles.Service.BackgroundServices;

/// <summary>
/// 自动根据字幕翻译数据
/// </summary>
/// <param name="serviceProvider"></param>
/// <param name="redisClient"></param>
public class AutoTranslationSubBackgroundService(IServiceProvider serviceProvider, RedisClient redisClient, ILogger<AutoTranslationSubBackgroundService> logger) : BackgroundService
{
    private IEventBus? _eventBus;

    private static bool IsRunning { get; set; }

    private static bool IsWantToDoItImmediately { get; set; }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using var serviceScope = serviceProvider.CreateScope();
        _eventBus = serviceScope.ServiceProvider.GetService<IEventBus>()!;
        logger.LogWarning("--后台自动翻译任务 开启");
        Init();
        // 使用 TaskCompletionSource 更好地控制任务生命周期
        var taskCompletionSource = new TaskCompletionSource<bool>();
        await Task.Run(async () =>
        {
            try
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    if (!IsRunning && !IsWantToDoItImmediately) //TODO:需要添加手动触发更新任务
                    {
                        await Task.Delay(20000, stoppingToken);
                        continue;
                    }

                    IsRunning = true;
                    try
                    {
                        if (!IsWantToDoItImmediately && !WhetherToExecuteTheTask())
                        {
                            await Task.Delay(10000, stoppingToken);
                            continue;
                        }

                        if (IsWantToDoItImmediately) IsWantToDoItImmediately = false;
                        logger.LogInformation("--更新字幕数据对称翻译 开始");
                        await RunTask();
                        var dateTime = DateTime.Now;
                        await redisClient.SetAsync(CacheCommon.AutoTranslationTask, dateTime);
                        logger.LogInformation("--更新字幕数据对称翻译 结束");
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, "--更新字幕数据对称翻译 异常");
                    }
                    finally
                    {
                        IsRunning = false;
                    }
                }

                taskCompletionSource.SetResult(true);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "后台任务异常");
                taskCompletionSource.SetException(ex);
            }
        }, stoppingToken);

        // 等待任务完成或发生异常
        await taskCompletionSource.Task;
    }

    /// <summary>
    /// 运行字幕翻译任务
    /// </summary>
    private async Task RunTask()
    {
        logger.LogInformation("--自动翻译字幕 开始");
        var isRun = true;
        var subtitle = new List<Auto_Subtitle>();
        var len = 0;
        while (len < 10)
        {
            var query = new GetMediaRandomDataQuery();
            await _eventBus!.PublishAsync(query);
            var media = query.Result;
            if (media.Count == 0)
            {
                logger.LogWarning("--没有找到媒体数据");
                isRun = false;
                break;
            }

            //查询字幕
            var subtitleQuery = new GetSubtitleDataQuery(media);
            await _eventBus!.PublishAsync(subtitleQuery);
            if (subtitleQuery.Result == null || subtitleQuery.Result.Count == 0)
            {
                logger.LogWarning("--没有找到字幕数据");
                len++;
                continue;
            }

            //监测字幕是否已经翻译过
            var translateQuery = new GetTranslationQuery(subtitleQuery.Result);
            await _eventBus!.PublishAsync(translateQuery);
            if (translateQuery.Result == null || translateQuery.Result.Count == 0)
            {
                logger.LogWarning("--字幕已经翻译过");
                len++;
                continue;
            }

            subtitle = translateQuery.Result;
            break;
        }

        if (!isRun)
        {
            logger.LogWarning("--没有找到媒体数据");
            return;
        }

        var languageConversionQuery = new GetLanguageConversionListDataQuery();
        await _eventBus!.PublishAsync(languageConversionQuery);
        var languageConversion = languageConversionQuery.Result;
        //TODO: 语言转换列表需要更新
        //分组 同媒体下一组 ,同一种语言只保留一个
        var group = subtitle.GroupBy(x => x.VideoId);
        foreach (var item in group)
        {
            List<string> language = [];
            //合并媒体语言 根据语言转换表 列表中会出现转换表中不存在的语言 不存在的语言代表是原始文件的语言
            foreach (var languageItem in item)
            {
                if (languageItem.Language == null) continue;
                if (!languageConversion.TryGetValue(languageItem.Language, out var value)) continue;
                if (!language.Contains(value))
                    language.Add(value);
            }

            //翻译至少需要两个字幕  
            if (language.Count < 2)
            {
                logger.LogWarning("--翻译至少需要两个字幕");
                continue;
            }

            //组合不同语言的翻译
            Dictionary<string, (Auto_Subtitle, List<Auto_Subtitle>)> dic = new();
            foreach (var sitem in language)
            {
                //重复规则 中->英 就不需要 英->中 判断条件Language]
                //排除自己，并每个语言只保留一个
                List<string> list = [];
                List<string> qlist = [];
                foreach (var keyValuePair in languageConversion)
                    if (keyValuePair.Value == sitem)
                    {
                        if (list.Contains(keyValuePair.Key)) continue;
                        list.Add(keyValuePair.Key);
                    }
                    else
                    {
                        if (qlist.Contains(keyValuePair.Key)) continue;
                        qlist.Add(keyValuePair.Key);
                    }

                var source = item.FirstOrDefault(x => list.Contains(x.Language));
                if (source == null)
                {
                    logger.LogWarning("--没有找到翻译数据");
                    continue;
                }

                // var data = item.Where(x => qlist.Contains(x.Language)).ToList();
                //每个语言只保留一个
                var data = item.Where(x => qlist.Contains(x.Language)).ToList();
                data = data.GroupBy(x => x.Language).Select(x => x.First()).ToList();
                dic.Add(sitem, (source, data));
            }

            //TODO： 语言互相转换 需要修补
            foreach (var citem in dic)
            {
                var (source, list) = citem.Value;
                foreach (var autoSubtitle in list)
                    try
                    {
                        var translate = new StartSubtitleTranslationExtractionCommand(source, autoSubtitle);
                        await _eventBus!.PublishAsync(translate);
                    }
                    catch (Exception e)
                    {
                        logger.LogError(e, "--自动翻译字幕 异常");
                    }
            }
        }

        logger.LogInformation("--自动翻译字幕 结束");
    }

    /// <summary>
    /// 运行时间 一天一次
    /// </summary>
    /// <returns></returns>
    private bool WhetherToExecuteTheTask()
    {
        var dateTime = redisClient.Get<DateTime?>(CacheCommon.AutoTranslationTask);
        if (dateTime == null) return true;
        var time = DateTime.Now;
        return time.Subtract(dateTime.Value).TotalHours > 24;
    }

    /// <summary>
    /// 初始化人工任务数据提交
    /// </summary>
    private void Init()
    {
        redisClient.Subscribe(CacheCommon.AutoTranslationSubBackgroundServiceKey, async (_, x) =>
        {
            //
            if (x is not nameof(AutoTranslationSubBackgroundService)) return;
            logger.LogWarning("--自动字幕翻译 收到缓存更新通知");
            IsWantToDoItImmediately = true;
        });
    }
}